package DesignPattern.Singleton;

public class Singleton2 {//懒汉式单例：在第一次调用时实例化自己。

    private Singleton2() {
        //私有构造方法
    }
    public static Singleton2 s = null;
    public static Singleton2 getsingle() {
        s = new Singleton2();//实例化
        return s;//看这里
    }
}
/*为了保证懒汉式的线程安全，通常有三种方法：

1. 全局访问点加同步。  当我要获取对象的时候，锁起来-进入方法-获取对象
由于synchronized是锁方法, 当两个线程都要进入getsingle()时, 只有一个能进入, 并创建出实例,
然后另外一个进入后, 判断 s不为null, 然后直接得到s。
这种做法是没有错误的. 但是由于线程都需要通过getsingle()来获取对象,
所以getsingle()调用频率很高, 所以线程被锁的频率也很高, 所以这种做法效率低。
简言之，不管对象有没有被创建，其余线程都只能等待这个方法的锁。
class Single1{
	private Single1() {
		//私有构造方法
	}
	public static Single1 s=null;
	public static synchronized Single1 getsingle() {
		s=new Single1();//实例化
		return s;
	}
}

2. 双重检查锁定。   当我要获取对象的时候，进入方法-锁起来-获取对象
由于上述都是在等待同步方法的锁，很容易想到把synchronized放在方法里面，这样可以避免方法的阻塞。
class Single2{
	private Single2() {
		//私有构造方法
	}
	public static Single2 s=null;
	public static Single2 getsingle() {
		if(s==null) {
			synchronized(Single2.class) {
					s=new Single2();//实例化
			}
		}
		return s;
	}
}
这种写法看似没有问题, 其实却有一个很大的隐患,
在于：如果两个线程同时执行getsingle(),判断 instance都不为null后, 进入if判断语句。这个时候一个线程获得锁, 然后进入new了一个对象,
 并开心地执行完了。这个时候另外一个线程获得了锁, 但让它也不会再去判断 s是否为null，所以它也会再执行一次new操作。所以这里执行了两次new操作。
当然最后s还是只指向后一次new的对象。
所以这个时候需要双重锁定, 就是在 synchronized中再加一次 null判断, 如下:
class Single3{  当我要获取对象的时候，进入方法-锁起来-判断是否已经有了-获取对象
	private Single3() {
		//私有构造方法
	}
	public static Single3 s=null;
	public static Single3 getsingle() {
		if(s==null) {
			synchronized(Single3.class) {
				if(s==null) {//注意是这里加了一个判断
					s=new Single3();//实例化
				}
			}
		}
		return s;
	}
}

3. 静态内部类：既实现了线程安全，又避免了同步带来的性能影响。
class Single4{   搞这么多没用，直接设成静态类解决
    private static class LazyHolder{
        private static final Single4 single4 = new Single4();
    }
    private Single4() {
        //私有构造方法
    }
    public static final  Single4 getsingle(){
        return LazyHolder.single4;
    }
}
* */
